#pragma once
#include <Rz/Object.h>
#include <Rz/IEquatable.h>
#include <Rz/Collections/IList.h>

#include <array>

namespace Rz { namespace Collections {

template <typename T, size_t N>
class Array :
	public Object,
	public IList<T>,
	public IEquatable<Array<T, N>>
{
	typedef std::array<T, N> ArrayType;

	public:
		RZ_RTTI(Rz::Collections, Array);
		RZ_RTTI_IMPLEMENTS(Object, IList<T>, IEquatable<Array<T, N>>);
		RZ_RTTI_TEMPLATES(T /*, NonObjectType<N>*/);
		RZ_RTTI_END;

		RZ_TYPEWRAPPER_IMPLEMENT(T);

		Array();
		Array(const Array<T, N>& arr);
		
		Pointer Data();
		ConstPointer Data() const;

		void Empty();

		Array<T, N>& operator = (const Array<T, N>& arr);

		// IList
		virtual ConstReference At(SizeType index) const override;
		virtual Reference At(SizeType index) override;

		virtual ConstReference operator [] (SizeType index) const override;
		virtual Reference operator [] (SizeType index) override;

		virtual SizeType GetCount() const override;

		// IEquatable
		virtual bool Equals(const Array<T, N>& r) const override;
                
        virtual bool operator == (const Array<T, N>& r) const override;
		virtual bool operator != (const Array<T, N>& r) const override;

		// IEnumerable
		RZ_IENUMERABLE_IMPLEMENT_DEFAULT(_array);

	private:
		std::array<T, N> _array;
};

} }

#include "Array.inl"
